package controller;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import parsers.RegimenAlimenticioParser;
import model.Compuesto;
import model.Consumo;
import model.ConsumoDiario;
import model.Nutriente;
import model.RegimenAlimenticio;
















import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.GenericRawResults;
import com.j256.ormlite.dao.RuntimeExceptionDao;
import com.j256.ormlite.stmt.QueryBuilder;
import dtos.RegimenAlimenticioDTO;
import DB.DatabaseHelper;
import android.annotation.SuppressLint;
import android.content.Context;

@SuppressLint("SimpleDateFormat")
public class RegimenAlimenticioController {
	private static RegimenAlimenticioController instance = null;
	protected RegimenAlimenticioController() {
	}
	public static RegimenAlimenticioController getInstance() {
		if(instance == null) {
    	  instance = new RegimenAlimenticioController();
		}
		return instance;
	}
	public Map<String, Float> index(Context context){
		try {
		DatabaseHelper db =new DatabaseHelper(context);
			RuntimeExceptionDao<RegimenAlimenticio, Integer> regimenDao = db.getRegimenAlimenticioDaoException();
			RegimenAlimenticio info = regimenDao.queryBuilder().orderBy("id", false).queryForFirst();
			if(info!=null){
				Map<String, Float> medidas=new HashMap<String, Float>();
				medidas.put("liquido", info.getLiquido());
				medidas.put("diuresis", info.getDiuresis());
				medidas.put("peso", info.getPeso());
				medidas.put("pesoSeco", info.getPesoSeco());
				medidas.put("altura", info.getAltura());
				Dao<Nutriente, Integer> nutrienteDAO = db.getNutrienteDao();
				Object[] compuestos =  info.getCompuestos().toArray();
				for (Object compuesto : compuestos) {
					Nutriente nutriente = nutrienteDAO.queryForId(((Compuesto) compuesto).getNutriente().getId());
					medidas.put(nutriente.getNombre(), ((Compuesto) compuesto).getCantidad());
				}
				return medidas;
			}
			else{
				return null;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null; 
	}
	
	public void add(Context context,Map<String, Float> medidas){
		try {
			DatabaseHelper db =new DatabaseHelper(context);
			RegimenAlimenticio info= new RegimenAlimenticio();
			Dao<Nutriente, Integer> nutrienteDAO = db.getNutrienteDao();
			
			QueryBuilder<Nutriente, Integer> query = nutrienteDAO.queryBuilder();
			Nutriente potasio = query.where().eq("nombre","Potasio").queryForFirst();
			Nutriente calcio = query.where().eq("nombre","Calcio").queryForFirst();
			Nutriente proteina = query.where().eq("nombre","Proteina").queryForFirst();
			Nutriente fosforo = query.where().eq("nombre","Fosforo").queryForFirst();
			Nutriente sodio = query.where().eq("nombre","Sodio").queryForFirst();
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Date hoy = sdf.parse(sdf.format(new Date()));
			
			Dao<RegimenAlimenticio, Integer> regimenDAO = db.getRegimenAlimenticioDao();	
			info.setAltura(medidas.get("altura"));
			info.setPeso(medidas.get("peso"));
			info.setPesoSeco(medidas.get("pesoSeco"));
			info.setDiuresis(medidas.get("diuresis"));
			info.setLiquido(medidas.get("liquido"));
			info.setFecha(hoy);
			regimenDAO.create(info);
			
			Dao<Compuesto, Integer> compuestoDAO = db.getCompuestoDao();
			
			Compuesto compuesto =new Compuesto();
			compuesto.setNutriente(sodio);
			compuesto.setCantidad(medidas.get("sodio"));
			compuesto.setRegimenAlimenticio(info);
			compuestoDAO.create(compuesto);
			/*Guardar y levantar compuesto*/
			
			compuesto.setNutriente(calcio);
			compuesto.setCantidad(medidas.get("calcio"));
			compuesto.setRegimenAlimenticio(info);
			compuestoDAO.create(compuesto);
			/*Guardar y levantar compuesto*/
			
			compuesto.setNutriente(proteina);
			compuesto.setCantidad(medidas.get("proteina"));
			compuesto.setRegimenAlimenticio(info);
			compuestoDAO.create(compuesto);
			/*Guardar y levantar compuesto*/
			
			compuesto.setNutriente(fosforo);
			compuesto.setCantidad(medidas.get("fosforo"));
			compuesto.setRegimenAlimenticio(info);
			compuestoDAO.create(compuesto);
			/*Guardar y levantar compuesto*/
			
			compuesto.setNutriente(potasio);
			compuesto.setCantidad(medidas.get("potasio"));
			compuesto.setRegimenAlimenticio(info);
			compuestoDAO.create(compuesto);
			/*Guardar y levantar compuesto*/			
			
			Dao<ConsumoDiario, Integer> consumoDiarioDao = db.getConsumoDiarioDao();
			if(consumoDiarioDao.countOf()==0){
				ConsumoDiarioController.getInstance().add(context);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	

	}
		/*public RegimenAlimenticioDTO getRegimenAlimenticio (Context context, Date dia){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Date hoy = sdf.parse(sdf.format(dia));
			DatabaseHelper db =new DatabaseHelper(context);
			Dao<RegimenAlimenticio, Integer> regimenDao= db.getRegimenAlimenticioDao();
			RuntimeExceptionDao<RegimenAlimenticio, Integer> regimenDao = db.getRegimenAlimenticioDaoException();
			RegimenAlimenticio info = regimenDao.queryBuilder().where().eq("fecha_diaria", hoy.getTime()).queryForFirst();
			Date fecha = sdf.parse(sdf.format(info.getFecha()));
		}*/
		
	public RegimenAlimenticioDTO cargoRegimenAlimenticioHoy(Context context, Date dia){
		try {
			DatabaseHelper db =new DatabaseHelper(context);
			Dao<RegimenAlimenticio, Integer> regimenDao= db.getRegimenAlimenticioDao();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Date hoy = sdf.parse(sdf.format(dia));
			RegimenAlimenticio info = regimenDao.queryBuilder().where().eq("fecha_regimen", hoy).queryForFirst();
			if(info!=null){
				ArrayList<Compuesto> compuestos= (ArrayList<Compuesto>) db.getCompuestoDao().queryBuilder().where().eq("regimen_alimenticio_id", info.getId()).query();
				for (Compuesto compuesto : compuestos) {
					compuesto.setNutriente(db.getNutrienteDao().queryForId(compuesto.getNutriente().getId()));
				}
				return RegimenAlimenticioParser.getInstance().fromModelToDTOEager(info,compuestos);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public List<String> obtenerCantidadesQuePuedoConsumir(Context context){
		List<String> respuesta=new ArrayList<String>();
		try {
			DatabaseHelper db=new DatabaseHelper(context);
			Dao<RegimenAlimenticio, Integer> regimenDao = db.getRegimenAlimenticioDao();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");      
		    Date hoy= sdf.parse(sdf.format(new Date()));
			GenericRawResults<String[]> rawResults = regimenDao.queryRaw("select * from consumos inner join alimentos on consumos.alimento_id=alimentos.id where alimentos.nombre not like '%Liquido%' and "+ Consumo.FECHA_CONSUMO_FIELD_NAME +" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000)));
			List<String[]> results = rawResults.getResults();
			//Veo si existen consumos del dia la fecha
			if(!results.isEmpty()){
			// Query que obtiene la cantidad de nutrientes que se consumieron en el dia 
			//y resta contra las de regimen alimenticio del dia 
			//solo devuelve en el caso que la cantidad consumida sea mayor al regimen
			rawResults =regimenDao.queryRaw(
					"select regimen.nutriente_id,regimen.nombre,cantidad-consumido from (select nutriente_id,nutrientes.nombre,compuestos.cantidad from (select * from regimenes_alimenticios where id=(select regimen_alimenticio_id from consumos_diarios ORDER BY id DESC LIMIT 1)) as regimen_alimenticio inner join compuestos on compuestos.regimen_alimenticio_id=regimen_alimenticio.id inner join nutrientes on nutrientes.id=compuestos.nutriente_id group by (compuestos.nutriente_id)) as regimen "
					+ "inner join "
					+ "(select nutriente_id,nutrientes.nombre,sum(compuestos.cantidad * consumos.cantidad) as consumido from alimentos inner join consumos on alimentos.id=consumos.alimento_id inner join compuestos on compuestos.alimento_id=alimentos.id inner join nutrientes on nutrientes.id=compuestos.nutriente_id where "+Consumo.FECHA_CONSUMO_FIELD_NAME+" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000))+" group by (compuestos.nutriente_id)) as consumo on consumo.nutriente_id=regimen.nutriente_id");
			results = rawResults.getResults();
			if(!results.isEmpty()){
				for (String[] strings : results) {
					respuesta.add(strings[2]+" "+strings[1] );
				}
				
			}
		}
			else{
				rawResults =regimenDao.queryRaw(
						"select nutriente_id,nutrientes.nombre,compuestos.cantidad from (select * from regimenes_alimenticios where id=(select regimen_alimenticio_id from consumos_diarios ORDER BY id DESC LIMIT 1)) as regimen_alimenticio inner join compuestos on compuestos.regimen_alimenticio_id=regimen_alimenticio.id inner join nutrientes on nutrientes.id=compuestos.nutriente_id group by (compuestos.nutriente_id) ");
						results = rawResults.getResults();
						if(!results.isEmpty()){
							for (String[] strings : results) {
								respuesta.add(strings[2]+" "+strings[1] );
							}
							
						}
			}
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return respuesta;
	}
	
	public ArrayList<Integer> obtenerCantidadesQuePuedoConsumirLiquido(Context context) {
		ArrayList<Integer> consumirList=new ArrayList<Integer>();
		try {
			DatabaseHelper db=new DatabaseHelper(context);
			Dao<RegimenAlimenticio, Integer> regimenDao = db.getRegimenAlimenticioDao();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");      
		    Date hoy= sdf.parse(sdf.format(new Date()));
			GenericRawResults<String[]> rawResults = regimenDao.queryRaw("select * from consumos inner join alimentos on consumos.alimento_id=alimentos.id where alimentos.nombre like '%Liquido%' and "+ Consumo.FECHA_CONSUMO_FIELD_NAME +" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000)));
			List<String[]> results = rawResults.getResults();
			//Veo si existen consumos de liquido del dia la fecha
			if(!results.isEmpty()){
			// Query que obtiene la cantidad de nutrientes que se consumieron en el dia 
			//y resta contra las de regimen alimenticio del dia 
			//solo devuelve en el caso que la cantidad consumida sea mayor al regimen
			rawResults =regimenDao.queryRaw("select regimen.cantidad,(regimen.cantidad-sum (consumos.cantidad)) from (select liquido as cantidad,regimenes_alimenticios.id  from regimenes_alimenticios where id=(select regimen_alimenticio_id from consumos_diarios ORDER BY id DESC LIMIT 1)) as regimen inner join consumos_diarios on consumos_diarios.regimen_alimenticio_id=regimen.id inner join consumos on consumos.consumo_diario_id=consumos_diarios.id inner join alimentos on alimentos.id=consumos.alimento_id where alimentos.nombre like '%Liquido%' and "+Consumo.FECHA_CONSUMO_FIELD_NAME+" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000))+"");
			results = rawResults.getResults();
			if(!results.isEmpty()){
				int consumir=0;
				int consumirReg=0;
				for (String[] strings : results) {
					consumir= Integer.parseInt(strings[1]);
					consumirReg= Integer.parseInt(strings[0]);
				}
				if(consumir<0){
					consumirList.add(consumirReg);
					consumirList.add(consumir*(-1)+consumirReg);
				}
				else{
					consumirList.add(consumirReg);
					consumirList.add(consumirReg-consumir);
				}
				
			}
		}
			else{
				//OSINO devuelvo todo lo que puedo consumir de liquido en el dia
				rawResults =regimenDao.queryRaw(
						"select regimen_alimenticio.liquido from (select * from regimenes_alimenticios where id=(select regimen_alimenticio_id from consumos_diarios ORDER BY id DESC LIMIT 1)) as regimen_alimenticio");
						results = rawResults.getResults();
						if(!results.isEmpty()){
							int consumirReg=0;
							for (String[] strings : results) {
								consumirReg= Integer.parseInt(strings[0]);
							}
							consumirList.add(consumirReg);
							consumirList.add(0);
						}
			}
			return consumirList;
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return consumirList;
	}
	public RegimenAlimenticioDTO obtenerRegimenAlimenticioPorConsumoDiario(Context context, Date date_inicio) {
	    try {
	    	DatabaseHelper db=new DatabaseHelper(context);
	    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");      
			Date hoy= sdf.parse(sdf.format(date_inicio));
			
			//Obtengo el consumo diario de la fecha
			Dao<ConsumoDiario, Integer> cdDAO = db.getConsumoDiarioDao();
			ConsumoDiario consumoDiario = cdDAO.queryBuilder().where().eq("fecha_diaria", hoy).queryForFirst();
			
			if(consumoDiario!=null){
				//Obtengo el regimen alimenticio del consumo diario que encontre
				Dao<RegimenAlimenticio, Integer> regDAO = db.getRegimenAlimenticioDao();
				RegimenAlimenticio regimen=regDAO.queryForId(consumoDiario.getPuedoConsumir().getId());
				if(regimen!=null){
					ArrayList<Compuesto> compuestos= (ArrayList<Compuesto>) db.getCompuestoDao().queryBuilder().where().eq("regimen_alimenticio_id", regimen.getId()).query();
					for (Compuesto compuesto : compuestos) {
						compuesto.setNutriente(db.getNutrienteDao().queryForId(compuesto.getNutriente().getId()));
					}
					return RegimenAlimenticioParser.getInstance().fromModelToDTOEager(regimen, compuestos);
				}
			}
			else{
				//Si no existe el consumoDiario del dia de la fecha, lo creo
				ConsumoDiario consumo=ConsumoDiarioController.getInstance().add(context);
				RegimenAlimenticioDTO regimen=RegimenAlimenticioParser.getInstance().fromModelToDTOLazy(consumo.getPuedoConsumir());
				return regimen;
			}
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}